﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Hive.Core;

namespace Hive.NewBot
{
    public enum CommandType
    {
        Unknown, Food, Explore, Patrol
    }
    public class Command
    {
        public CommandType Type { get; private set; }
        public Command(CommandType type)
        {
            Performers = new List<Performer>();
            Weight = 1.0f;
            this.Type = type;
        }

        public float Weight { get; set; }
        public Location Target { get; set; }
        public List<Performer> Performers { get; set; }

        public void AddAnt(Ant ant)
        {
            var p = new Performer { Ant = ant, Command = this };
            p.Route = Env.Map.BuildPath(ant.Location, Target);
            Performers.Add(p);
        }

        public IEnumerable<Order> Execute()
        {
            foreach (var p in Performers)
            {
                if (!p.IsComplete())
                    yield return new Order { Destination = p.Route.First(), Performer = p };
            }
        }

        public void RemoveAnt(Ant ant)
        {
            Performers.RemoveAll(p => p.Ant == ant);
        }

        public IEnumerable<int> CurrentEfficiencies()
        {
            return Performers.Select(p => (int)(Weight * GetEfficiencyByDistance(p.Route.Count)));
        }

        public IEnumerable<int> CalculateEfficiencies(List<Ant> ants)
        {
            return ants.Select(a => (int)(Weight * GetEfficiencyByDistance(Env.Map.GetDistance(a.Location, Target))));
        }

        public static int GetEfficiencyByDistance(int distance)
        {
            if (distance == 0)
                return 0;

            var max = Env.Map.Height + Env.Map.Width;
            if (distance > max) 
                distance = max;
            return (int)Math.Round(100.0 * (max - distance) / max);
        }

        public override int GetHashCode()
        {
            return Target.GetHashCode();
        }

        public override bool Equals(object obj)
        {
            var other = obj as Command;
            if (other == null)
                return false;

            return other.Target == this.Target;
        }
    }

    public class Performer
    {
        public Ant Ant { get; set; }
        public List<Location> Route { get; set; }
        public Command Command { get; set; }

        public void Advance()
        {
            var f = Route.First();
            Ant.Move(f);
            Route.Remove(f);
        }

        public virtual bool IsComplete()
        {
            return !Route.Any();
        }
    }
}
